﻿package framework.core;

import java.util.* ;
import java.sql.*;

import com.hitrust.gs.dao.GSCompanyMessageDao;

import system.base.CompanyMessageSrv;
import system.data.CompanyMessageData;


//import com.bashi.v2.log.Log;
public abstract class Table extends DBData
{
	protected int ms_new_flag = ConstDefine.YES ;
	//protected int ms_modify_flag = ConstDefine.NO;
	
	//database callback functions
	public void canInsert(DBConnection con) throws Exception
	{
	}
	public void beforeInsert(DBConnection con) throws Exception
	{
	}
	public void afterInsert(DBConnection con) throws Exception
	{
	}
	public void canDelete(DBConnection con) throws Exception
	{
	}
	public void beforeDelete(DBConnection con) throws Exception
	{
	}
	public void afterDelete(DBConnection con) throws Exception
	{
	}
	
	public void canUpdate(DBConnection con) throws Exception
	{
	}
	public void beforeUpdate(DBConnection con) throws Exception
	{
	}
	public void afterUpdate(DBConnection con) throws Exception
	{
	}
	
	public void beforeChange(DBConnection con) throws Exception
	{
	}
	public void afterChange(DBConnection con) throws Exception
	{
	}
	
	//data check callback functions
	public void checkData(DBConnection con) throws Exception
	{
	}

	//子类覆盖函数
	protected void getUnique(DBConnection con) throws Exception
	{
	}
	private Vector mDirtys = new Vector();
	public abstract Vector getFields();
	public abstract Value get(String fieldName);
	public abstract String getTableName();
	public abstract String getBackupTableName();  //得到备份表名
	public abstract String getBackupSeqName();    //得到备份SEQ名
	
	//public abstract void initObject(java.sql.ResultSet rs) throws Exception;
	
	//functions
	protected void markDirty(String name)
	{
		if(!mDirtys.contains(name))
			mDirtys.add(name);
	}
	
	//检查数据完整性
	protected void checkTableData(DBConnection con) throws Exception
	{
		Vector fields = getFields();
		Field f = null;
		Value v = null;
		for(int i=0;i<fields.size();i++)
		{
			f = (Field)fields.get(i);
			v = get(f.getName());
			int type = f.getType();
			
			if(type==Value.TYPE_INT)
			{
				
			}
			else if(type==Value.TYPE_DOUBLE)
			{
				
			}
			else if(type==Value.TYPE_STRING)
			{
				if(!f.canNull())
				{
					if(v.isNull())
					{
						throw new BizException(f.getName()+"字段必须填写!");
					}
				}
				if(f.getLen()>0)
				{
					if(v.getString().length()>f.getLen())
					{
						throw new BizException(f.getName()+"字段最大长度为"+f.getLen()+"!");
					}
				}
			}
			else if(type==Value.TYPE_DATE_UTIL)
			{
				if(!f.canNull())
				{
					if(v.isNull())
					{
						throw new BizException(f.getName()+"字段必须填写");
					}
				}
			}
			else 
			{
				//can not be here
			}

			//枚举检查
			if(f.getEnumCount()>0)
			{
				boolean ok = false;
				for(int j=0;j<f.getEnumCount();j++)
				{
					if(f.getEnumValue(j).equals(v))
					{
						ok = true;
					}
				}
				if(!ok)
				{
					throw new BizException(f.getName()+"字段值("+v+")超出范围!");
				}
			}
			
		}
	}
	
	public boolean exist(DBConnection con,Conditions cs) throws Exception
	{
		DBEngine.checkCon(con);
		if(null==cs || cs.getParamCount()==0) throw new Exception("Table.exist():没有设置检查条件!");
		int count = DBEngine.doTableCount(con,getTableName(),cs);
		return count>0 ;
	}
	
	protected Vector getPKFields()
	{
		Vector pks = new Vector();
		Vector fields = getFields();
		Field f = null;
		for(int i=0;i<fields.size();i++)
		{
			f = (Field)fields.get(i);
			if(f.isPrimary())
			{
				pks.add(f);
			}
		}
		return pks ;
	}
	
	public boolean exist(DBConnection con,int id) throws Exception
	{
		Vector pks = getPKFields();
		if(pks.size()!=1) throw new Exception("Table.exist():主键字段的数目不正确!");
		
		Field f = (Field)pks.get(0);
		
		if(f.getType()!=Value.TYPE_INT)
		{
			throw new Exception("Table.exist():主键数据类型不正确!");
		}
		
		Conditions cs = new Conditions();
		cs.add(f.getName(),id);
		return exist(con,cs);
	}
	
	//删除纪录
	protected static void delete(DBConnection con,String table,Conditions cs) throws Exception
	{
		try
		{
			DBEngine.checkCon(con);
			if(null==cs || cs.getParamCount()==0) throw new Exception("Table.delete():没有设置删除条件,不允许删除操作!");
			String sql = "delete from " + table ;
			DBEngine.doUpdate(con,sql,cs);
		}
		catch(SQLException e)
		{
			if(e.getErrorCode()==ConstDefine.ORACEL_FK_ERROR_CODE)
			{
				throw new BizException("数据已经被使用,无法删除!");
			}
		}
	}
	
	public void delete(DBConnection con) throws Exception
	{
		DBEngine.checkCon(con);
		
		//callback
		canDelete(con);
		beforeChange(con);
		beforeDelete(con);
	 	
	 	Conditions cs = new Conditions();
		Vector fields = getFields();
		Field f ;
		for(int i=0;i<fields.size();i++)
		{
			f = (Field)fields.get(i);
			if(f.isPrimary())
			{
				cs.add(f.getName(),get(f.getName()));
			}
		}
		delete(con,getTableName(),cs);
		
		//callback
		afterDelete(con);
		afterChange(con);
	}
	
	//insert
	protected void insert(DBConnection con) throws Exception 
	{
		DBEngine.checkCon(con);
		
		//calllback
		canInsert(con);
		beforeChange(con);
		beforeInsert(con);

		//check
		checkTableData(con);
		checkData(con);
		
		String sql = "insert into " + getTableName() + " (";
		String sql_values = " values (";
		
		Vector fields = getFields();
		Field f = null;
		for(int i=0;i<fields.size();i++)
		{
			f = (Field)fields.get(i);
			if(i==0)
			{
				sql += f.getName();
				sql_values += "?";
			}
			else
			{
				sql += "," + f.getName();
				sql_values += ",?";
			}
		}
		sql += ") " ;
		sql_values += ")";
		sql += sql_values;

		DBPreparedStatement pst = con.prepareStatement(sql);
		for(int i=0;i<fields.size();i++)
		{
			f = (Field)fields.get(i);
			pst.setParam(i+1,get(f.getName()));
		}
		pst.executeUpdate();
		pst.close();	
		ms_new_flag = ConstDefine.NO ;
		//ms_modify_flag = ConstDefine.NO;

		//callback
		afterInsert(con);
		afterChange(con);
	}
	
	protected void update(DBConnection con) throws Exception
	{
		DBEngine.checkCon(con);
		
		//callback
		canUpdate(con);
		beforeUpdate(con);
		beforeChange(con);
		
		//check
		checkData(con);
		
		
		String sql = "update " + getTableName() + " " ;
		Vector fields = getFields();
		Field f = null;
		
/*		
		boolean first_pk = true ;
		
		for(int i=0;i<fields.size();i++)
		{
			f = (Field)fields.get(i);
			if(i==0)
			{
				sql += " set "+f.getName()+"=? ";
			}
			else
			{
				sql += ","+f.getName()+"=?";
			}
		}
		
		for(int i=0;i<fields.size();i++)
		{
			f = (Field)fields.get(i);
			if(f.isPrimary())
			{
				if(first_pk)
				{
					sql += " where "+f.getName()+"=? ";
					first_pk = false;		
				}
				else
				{
					sql += " and "+f.getName()+"=?" ;
				}
			}
		}
		DBPreparedStatement pst = con.prepareStatement(sql);
		int count = 1 ;
		for(int i=0;i<fields.size();i++)
		{
			f = (Field)fields.get(i);
			pst.setParam(count++,get(f.getName()));
		}
		for(int i=0;i<fields.size();i++)
		{
			f = (Field)fields.get(i);
			if(f.isPrimary())
			{
				pst.setParam(count++,get(f.getName()));
			}
		}
*/	
		boolean first_pk = true ;
		if(mDirtys.size() <= 0) return;
		
		for(int i=0;i<mDirtys.size();i++)
		{
			String name = (String)mDirtys.get(i);
			if(i==0)
			{
				sql += " set "+name+"=? ";
			}
			else
			{
				sql += ","+name+"=?";
			}
		}
		
		for(int i=0;i<fields.size();i++)
		{
			f = (Field)fields.get(i);
			if(f.isPrimary())
			{
				if(first_pk)
				{
					sql += " where "+f.getName()+"=? ";
					first_pk = false;		
				}
				else
				{
					sql += " and "+f.getName()+"=?" ;
				}
			}
		}
		DBPreparedStatement pst = con.prepareStatement(sql);
		int count = 1 ;
		for(int i=0;i<mDirtys.size();i++)
		{
			String name = (String)mDirtys.get(i);
		//	f = (Field)fields.get(i);
			pst.setParam(count++,get(name));
		}
		for(int i=0;i<fields.size();i++)
		{
			f = (Field)fields.get(i);
			if(f.isPrimary())
			{
				pst.setParam(count++,get(f.getName()));
			}
		}
		pst.executeUpdate();
		pst.close();
		ms_new_flag = ConstDefine.NO ;
		//ms_modify_flag = ConstDefine.NO;
		
		//callback
		afterUpdate(con);
		afterChange(con);
			
	}
	
	public void save(DBConnection con) throws Exception
	{
		DBEngine.checkCon(con);
		if(ms_new_flag==ConstDefine.YES)
		{
			getUnique(con);
			insert(con);
		}
		else
		{
			update(con);
		}
	}
	
	//*
	public ObjectList search(DBConnection con,Conditions conditions) throws Exception
	{
		return search(con,conditions,null);
	}
	
	/*
	public ObjectList search(DBConnection con,Conditions conditions,String sort) throws Exception
	{
		DBEngine.checkCon(con);
		String sql = "select * from " + getTableName();
		String sql1 = "select count(*) from " + getTableName();
		int rsCount = DBEngine.doCount(con, sql1, conditions);
		DateUtil startTime = new DateUtil();
		long start = System.currentTimeMillis();
		DBResult result = DBEngine.doSelect(con,sql,conditions,sort);
		ObjectList list = ObjectList.fromRs(getClass(),result.getRs());
		long end = System.currentTimeMillis();
		DateUtil endTime = new DateUtil();
		
		//PerformanceLog.addLog(con, getClass(), sql, rsCount, conditions, sort, startTime, endTime, end - start);
		result.clear();
		return list;
	}
	*/
	
	
    
    public ObjectList search(DBConnection con,Conditions conditions,String sort) throws Exception
    {
        DBEngine.checkCon(con);
        String sql = "select * from " + getTableName();
//      String sql1 = "select count(id) from " + getTableName();
//      int rsCount = DBEngine.doCount(con, sql1, conditions);
//      DateUtil startTime = new DateUtil();
//      long start = System.currentTimeMillis();
        DBResult result = DBEngine.doSelect(con,sql,conditions,sort);
        ObjectList list = ObjectList.fromRs(getClass(),result.getRs());
//      long end = System.currentTimeMillis();
//      DateUtil endTime = new DateUtil();
        
//      PerformanceLog.addLog(con, getClass(), sql, rsCount, conditions, sort, startTime, endTime, end - start);
        result.clear();
        return list;
    }	
		
	//*/

	/*
	public ObjectList search(DBConnection con,SearchEvent event) throws Exception
	{
		DBEngine.checkCon(con);
		String sql = "select * from " + getTableName();
		String sql1 = "select count(*) from " + getTableName();
		int rsCount = DBEngine.doCount(con, sql1, event.toConditions());
		int totalCount = 0;
		//if(getTableName().equalsIgnoreCase(OrderItem.TABLE_NAME))
		//	totalCount = OrderItem.getTotalRecordNum(con);
		//if(getTableName().equalsIgnoreCase(OrderItem.TABLE_NAME))
		//	totalCount = Item.getTotalRecordNum(con); 
		DateUtil startTime = new DateUtil();
		long start = System.currentTimeMillis();
		Conditions cs = event.toConditions(); 
		DBResult result = DBEngine.doSelect(con,sql,cs,event.getOrderField(),event.isOrderDesc());
		ObjectList list = ObjectList.fromRs(getClass(),result.getRs(),event.getPageSize(),event.getPageNum());
		long end = System.currentTimeMillis();
		DateUtil endTime = new DateUtil();
		//PerformanceLog.addLog(con, getClass(), sql, rsCount, event.toConditions(), event.getOrderField(), startTime, endTime, end - start);
		result.clear();
		return list;
	}
	*/
	
	   public ObjectList search(DBConnection con,SearchEvent event) throws Exception
	    {
	        DBEngine.checkCon(con);
	        String sql = "select * from " + getTableName();
	   
	        String sql1 = "select count(*) from " + getTableName() + " ";
	        
	        Conditions eventCs = event.toConditions();
	       // eventCs.add("1=1");
	        int rsCount = DBEngine.doCount(con, sql1, eventCs);
//	      int totalCount = 0;
//	      if(getTableName().equalsIgnoreCase(OrderItem.TABLE_NAME))
//	          totalCount = OrderItem.getTotalRecordNum(con);
//	      if(getTableName().equalsIgnoreCase(OrderItem.TABLE_NAME))
//	          totalCount = Item.getTotalRecordNum(con); 
//	      DateUtil startTime = new DateUtil();
//	      long start = System.currentTimeMillis();
	        Conditions cs = event.toConditions(); 
	        DBResult result = DBEngine.doSelect(con,sql,cs,event);
	        ObjectList list = ObjectList.fromRsMini(getClass(),result.getRs(),event.getPageSize(),event.getPageNum(), rsCount);
//	      long end = System.currentTimeMillis();
//	      DateUtil endTime = new DateUtil();
//	      PerformanceLog.addLog(con, getClass(), sql, rsCount, event.toConditions(), event.getOrderField(), startTime, endTime, end - start);
	        result.clear();
	        return list;
	    }
	   
	   
	   public ObjectList mySearch2(DBConnection con,SearchEvent event,String tj) throws Exception
	    {
		   	//CompanyMessageData md = new CompanyMessageData();
		   	GSCompanyMessageDao cmd = new GSCompanyMessageDao();
	        DBEngine.checkCon(con);
	        String sql = "select * from (select * from " + getTableName()+" "+tj+") ";
	   
	      //  String sql1 = "select * from (select count(*) from " + getTableName() + " "+tj+" )";
	        
	        Conditions eventCs = event.toConditions();
	        List lss = cmd.executeQuery2(sql,null);
	       // eventCs.add("1=1");
	        //int rsCount = DBEngine.doCount(con, sql1, eventCs);
	        Conditions cs = event.toConditions(); 
	        DBResult result = DBEngine.doSelect(con,sql,cs,event);
	        ObjectList list = ObjectList.fromRsMini(getClass(),result.getRs(),event.getPageSize(),event.getPageNum(),lss.size() );
//	      long end = System.currentTimeMillis();
//	      DateUtil endTime = new DateUtil();
//	      PerformanceLog.addLog(con, getClass(), sql, rsCount, event.toConditions(), event.getOrderField(), startTime, endTime, end - start);
	        result.clear();
	        return list;
	    }
	
	/*
	public boolean isNullField(ResultSet rs,String fName) throws Exception
	{
		String val = rs.getString(fName);
		return val==null;
	}
	public int getInt(ResultSet rs,String fName) throws Exception
	{
		if(isNullField(rs,fName))
		{
			return Value.NULL_INT;
		}
		return rs.getInt(fName);
	}
	public double getDouble(ResultSet rs,String fName) throws Exception
	{
		if(isNullField(rs,fName))
		{
			return Value.NULL_DOUBLE;
		}
		return rs.getDouble(fName);
	}
	public String getString(ResultSet rs,String fName) throws Exception
	{
		if(isNullField(rs,fName))
		{
			return "";
		}
		return rs.getString(fName);
	}
	*/
	/*
	public InputStream getBinaryStream(ResultSet rs,String fName) throws Exception
	{
		return rs.getBinaryStream(fName);
	}
	*/
	
	
	//add by twb @ 2004-10-15 to support backup 
	public int backup(DBConnection con) throws Exception 
	{
		DBEngine.checkCon(con);
		
		int backupId = DBEngine.getId(con,getBackupSeqName());
		
		String sql = "insert into " + getBackupTableName() + " (BACKUP_ID,";
		String sql_values = " values (?,";
		
		Vector fields = getFields();
		Field f = null;
		for(int i=0;i<fields.size();i++)
		{
			f = (Field)fields.get(i);
			if(i==0)
			{
				sql += f.getName();
				sql_values += "?";
			}
			else
			{
				sql += "," + f.getName();
				sql_values += ",?";
			}
		}
		sql += ") " ;
		sql_values += ")";
		sql += sql_values;

		DBPreparedStatement pst = con.prepareStatement(sql);
		
		int paramIndex = 1;
		pst.setInt(paramIndex++,backupId);
		for(int i=0;i<fields.size();i++)
		{
			f = (Field)fields.get(i);
			pst.setParam(paramIndex++,get(f.getName()));
		}
		pst.executeUpdate();
		pst.close();	
		
		return backupId ;
	}

	public String compare(Table t) throws Exception
	{
		Vector fields = getFields();
		
		String s = "";
		Value v1 ;
		Value v2 ;
		Field f ;
		for(int i=0;i<fields.size();i++)
		{
			f = (Field)fields.get(i);
			v1 = get(f.getName());
			v2 = t.get(f.getName());
			if(v1.equals(v2)) continue;
			s += f.getComment() + "："+v1.viewString()+"->" + v2.viewString() ;//+ Log.LOG_SEPARATE ;
		}
		if (s.equalsIgnoreCase(""))
			s = "<font color='red'>无改变!</font>";
		return s;
	}
}
